home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / omega / outil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-06  |  12.2 KB  |  579 lines

  1. /* copyright (c) 1987,1988 by Laurence Raphael Brothers */
  2. /* outils.c */
  3.  
  4. /* Random utility functions called from all over */
  5.  
  6. #include "oglob.h"
  7.  
  8. /* x and y on level? */
  9. int inbounds(x,y)
  10. int x,y;
  11. {
  12.   return((x>=0)&&(y>=0)&&(x<WIDTH)&&(y<LENGTH));
  13. }
  14.  
  15. /* RANDFUNCTION is defined in odefs.h */
  16. int random_range(k)
  17. int k;
  18. {
  19.   return( k==0 ? 0 : (int) RANDFUNCTION % k ) ;
  20. }
  21.  
  22.  
  23. /* modify absolute y coord relative to which part of level we are on */
  24. int screenmod(y)
  25. int y;
  26. {
  27.   return(y-ScreenOffset);
  28. }
  29.  
  30.  
  31. int offscreen(y)
  32. int y;
  33. {
  34.   return((y<0)||
  35.      (y<ScreenOffset) ||
  36.      (y>ScreenOffset+ScreenLength-1) ||
  37.      (y>LENGTH));
  38. }
  39.  
  40.  
  41. /* always hit on a natural 0; never hit on a natural 19 */
  42. int hitp(hit,ac)
  43. int hit,ac;
  44. {
  45.   int roll = random_range(20);
  46.   if (roll == 0) return(TRUE);
  47.   else if (roll == 19) return(FALSE);
  48.   else return((roll < (hit - ac)) ? TRUE : FALSE );
  49. }
  50.  
  51.  
  52.  
  53. /* this function doesnt seem to exist by itself... */
  54. int sign(n)
  55. int n;
  56. {
  57.   if (n == 0) return(0);
  58.   else return((n < 0) ? -1 : 1);
  59. }
  60.  
  61.  
  62. /* why load the math library.... */
  63. int max(a,b)
  64. int a,b;
  65. {
  66.   return((a>b) ? a : b);
  67. }
  68.  
  69. /* why load the math library.... */
  70. int min(a,b)
  71. int a,b;
  72. {
  73.   return((a<b) ? a : b);
  74. }
  75.  
  76.  
  77. /* number of moves from x1,y1 to x2,y2 */
  78. int distance(x1,y1,x2,y2)
  79. int x1,y1,x2,y2;
  80. {
  81.   return(max(abs(x2-x1),abs(y2-y1)));
  82. }
  83.  
  84.  
  85. /* can you shoot, or move monsters through a spot? */
  86. int unblocked(x,y)
  87. int x,y;
  88. {
  89.   if ((! inbounds(x,y)) ||
  90.       (Level->site[x][y].creature != NULL) ||
  91.       (Level->site[x][y].locchar == WALL) ||
  92.       (Level->site[x][y].locchar == PORTCULLIS) ||
  93.       (Level->site[x][y].locchar == STATUE) ||
  94.       (Level->site[x][y].locchar == HEDGE) ||
  95.       (Level->site[x][y].locchar == CLOSED_DOOR) ||
  96.       loc_statusp(x,y,SECRET) ||
  97.       ((x==Player.x) && (y==Player.y)))
  98.     return(FALSE);
  99.   else 
  100.     return(TRUE);
  101. }
  102.  
  103.  
  104. /* do monsters want to move through a spot */
  105. int m_unblocked(m,x,y)
  106. struct monster *m;
  107. int x,y;
  108. {
  109.   if ((! inbounds(x,y)) || ((x==Player.x) && (y==Player.y)))
  110.     return(FALSE);
  111.   else if ((Level->site[x][y].creature != NULL) ||
  112.        (Level->site[x][y].locchar == SPACE)) return(FALSE);
  113.   else if (m_statusp(m,ONLYSWIM)) 
  114.     return(Level->site[x][y].locchar == WATER);
  115.   else if ((Level->site[x][y].locchar == FLOOR) ||
  116.        (Level->site[x][y].locchar == OPEN_DOOR))
  117.     return(TRUE);
  118.   else if ((Level->site[x][y].locchar == PORTCULLIS) ||
  119.        (Level->site[x][y].locchar == WALL) ||
  120.        (Level->site[x][y].locchar == STATUE) ||
  121.        loc_statusp(x,y,SECRET))
  122.     return(m_statusp(m,INTANGIBLE));
  123.   else if (Level->site[x][y].locchar==WATER)
  124.     return(m_statusp(m,SWIMMING) || 
  125.        m_statusp(m,ONLYSWIM) ||
  126.        m_statusp(m,FLYING));
  127.   else if (Level->site[x][y].locchar == CLOSED_DOOR) {
  128.     if (m->movef==M_MOVE_SMART) {
  129.       mprint("You hear a door creak open.");
  130.       Level->site[x][y].locchar = OPEN_DOOR;
  131.       return(TRUE);
  132.     }
  133.     else if (random_range(m->dmg) > random_range(100)) {
  134.       mprint("You hear a door shattering.");
  135.       Level->site[x][y].locchar = RUBBLE;
  136.       return(TRUE);
  137.     }
  138.     else return(m_statusp(m,INTANGIBLE));
  139.   }
  140.   else if (Level->site[x][y].locchar == LAVA)
  141.     return((m_immunityp(m,FLAME) && 
  142.         m_statusp(m,SWIMMING)) ||
  143.        m_statusp(m,FLYING));
  144.   else if (Level->site[x][y].locchar == FIRE)
  145.     return(m_immunityp(m,FLAME));
  146.   else if ((Level->site[x][y].locchar == TRAP) ||
  147.        (Level->site[x][y].locchar == HEDGE) ||
  148.        (Level->site[x][y].locchar == ABYSS))
  149.     return((m->movef == M_MOVE_CONFUSED) ||
  150.        m_statusp(m,FLYING));
  151.   else return(TRUE);
  152. }
  153.  
  154.  
  155.  
  156. /* can you see through a spot? */
  157. int view_unblocked(x,y)
  158. int x,y;
  159. {
  160.   if (! inbounds(x,y)) return(FALSE);
  161.   else if ((Level->site[x][y].locchar == WALL) ||
  162.        (Level->site[x][y].locchar == STATUE) ||
  163.        (Level->site[x][y].locchar == HEDGE) ||
  164.        (Level->site[x][y].locchar == FIRE) ||
  165.        (Level->site[x][y].locchar == CLOSED_DOOR) ||
  166.        loc_statusp(x,y,SECRET))
  167.     return(FALSE);
  168.   else 
  169.     return(TRUE);
  170. }
  171.  
  172.  
  173. /* 8 moves in Dirs */
  174. void initdirs()
  175. {
  176.   Dirs[0][0] = 1;
  177.   Dirs[0][1] = 1;
  178.   Dirs[0][2] = -1;
  179.   Dirs[0][3] = -1;
  180.   Dirs[0][4] = 1;
  181.   Dirs[0][5] = -1;
  182.   Dirs[0][6] = 0;
  183.   Dirs[0][7] = 0;
  184.   Dirs[0][8] = 0;
  185.   Dirs[1][0] = 1;
  186.   Dirs[1][1] = -1;
  187.   Dirs[1][2] = 1;
  188.   Dirs[1][3] = -1;
  189.   Dirs[1][4] = 0;
  190.   Dirs[1][5] = 0;
  191.   Dirs[1][6] = 1;
  192.   Dirs[1][7] = -1;
  193.   Dirs[1][8] = 0;
  194. }
  195.  
  196.  
  197.  
  198.  
  199.  
  200. /* do_los moves pyx along a lineofsight from x1 to x2 */
  201. /* x1 and x2 are pointers because as a side effect they are changed */
  202. /* to the final location of the pyx */
  203. void do_los(pyx,x1,y1,x2,y2)
  204. char pyx;
  205. int *x1,*y1,x2,y2;
  206. {
  207.   int ox,oy,sx,sy,v;
  208.  
  209.   do {
  210.     ox = *x1;
  211.     oy = *y1;
  212.     sx=sign(x2-*x1);
  213.     sy=sign(y2-*y1);
  214.     if (abs(x2-*x1) > abs(y2-*y1))
  215.       *x1 += sx;
  216.     else if (abs(x2-*x1) < abs(y2-*y1))
  217.       *y1 += sy;
  218.     else {
  219.       *x1 += sx;
  220.       *y1 += sy;
  221.     }
  222.     Level->site[*x1][*y1].showchar = pyx;
  223.     /* delay enough to make pyx visible */
  224.     for(v=1;v<10;v++) plotchar(pyx,*x1,*y1);
  225.     plotspot(ox,oy,FALSE);
  226.   } while(unblocked(*x1,*y1) && ((*x1 != x2) || (*y1 != y2)));
  227.   
  228.   plotspot(*x1,*y1,FALSE);
  229.   levelrefresh();
  230. }
  231.  
  232.  
  233. /* This is the same as do_los, except we stop before hitting nonliving
  234. obstructions */
  235. void do_object_los(pyx,x1,y1,x2,y2)
  236. char pyx;
  237. int *x1,*y1,x2,y2;
  238. {
  239.   int ox,oy,sx,sy,v;
  240.  
  241.   do {
  242.     ox = *x1;
  243.     oy = *y1;
  244.     sx=sign(x2-*x1);
  245.     sy=sign(y2-*y1);
  246.     if (abs(x2-*x1) > abs(y2-*y1))
  247.       *x1 += sx;
  248.     else if (abs(x2-*x1) < abs(y2-*y1))
  249.       *y1 += sy;
  250.     else {
  251.       *x1 += sx;
  252.       *y1 += sy;
  253.     }
  254.     if (unblocked(*x1,*y1)) {
  255.       for(v=1;v<10;v++) plotchar(pyx,*x1,*y1);
  256.       Level->site[*x1][*y1].showchar = pyx;
  257.     }
  258.     plotspot(ox,oy,TRUE);
  259.   } while(unblocked(*x1,*y1) && ((*x1 != x2) || (*y1 != y2)));
  260.   
  261.   if ((! unblocked(*x1,*y1)) && (Level->site[*x1][*y1].creature == NULL)) {
  262.     *x1 = ox;
  263.     *y1 = oy;
  264.   }
  265.   plotspot(*x1,*y1,TRUE);
  266.   levelrefresh();
  267. }
  268.       
  269.     
  270.  
  271.  
  272. /* los_p checks to see whether there is an unblocked los from x1,y1 to x2,y2 */
  273. int los_p(x1,y1,x2,y2)
  274. int x1,y1,x2,y2;
  275. {
  276.   int sx,sy;
  277.   do {
  278.     sx=sign(x2-x1);
  279.     sy=sign(y2-y1);
  280.     if (abs(x2-x1) > abs(y2-y1))
  281.       x1 += sx;
  282.     else if (abs(x2-x1) < abs(y2-y1))
  283.       y1 += sy;
  284.     else {
  285.       x1 += sx;
  286.       y1 += sy;
  287.     }
  288.   } while (unblocked(x1,y1) && ((x1 != x2) || (y1 != y2)));
  289.   return((x1==x2) && (y1==y2));
  290. }
  291.  
  292.  
  293. /* view_los_p sees through monsters */
  294. int view_los_p(x1,y1,x2,y2)
  295. int x1,y1,x2,y2;
  296. {
  297.   int sx,sy;
  298.   do {
  299.     sx=sign(x2-x1);
  300.     sy=sign(y2-y1);
  301.     if (abs(x2-x1) > abs(y2-y1))
  302.       x1 += sx;
  303.     else if (abs(x2-x1) < abs(y2-y1))
  304.       y1 += sy;
  305.     else {
  306.       x1 += sx;
  307.       y1 += sy;
  308.     }
  309.   } while (view_unblocked(x1,y1) && ((x1 != x2) || (y1 != y2)));
  310.   return((x1==x2) && (y1==y2));
  311. }
  312.  
  313.  
  314.  
  315. int gamestatusp(flag)
  316. long flag;
  317. {
  318.   return(GameStatus&flag);
  319. }
  320.  
  321. void setgamestatus(flag)
  322. long flag;
  323. {
  324.   GameStatus |= flag;
  325. }
  326.  
  327. void resetgamestatus(flag)
  328. long flag;
  329. {
  330.   GameStatus &= ~flag;
  331. }
  332.  
  333.  
  334. /* returns the command direction from the index into Dirs */
  335. char inversedir(dirindex)
  336. int dirindex;      
  337. {
  338.   switch (dirindex) {
  339.     case 0:return('n');break;
  340.     case 1:return('u');break;
  341.     case 2:return('b');break;
  342.     case 3:return('y');break;
  343.     case 4:return('l');break;
  344.     case 5:return('h');break;
  345.     case 6:return('j');break;
  346.     case 7:return('k');break;
  347.   }
  348. }
  349.  
  350.  
  351. int calc_points()
  352. {
  353.   int i,points=0;
  354.   
  355.   if (gamestatusp(SPOKE_TO_DRUID)) points += 50;
  356.   if (gamestatusp(COMPLETED_CAVES)) points += 100;
  357.   if (gamestatusp(COMPLETED_SEWERS)) points += 200;
  358.   if (gamestatusp(COMPLETED_CASTLE)) points += 300;
  359.   if (gamestatusp(COMPLETED_ASTRAL)) points += 400;
  360.   if (gamestatusp(COMPLETED_VOLCANO)) points += 500;
  361.   if (gamestatusp(KILLED_DRAGONLORD)) points += 100;
  362.   if (gamestatusp(KILLED_EATER)) points += 100;
  363.   if (gamestatusp(KILLED_LAWBRINGER)) points += 100;
  364.  
  365.   points += Player.xp/50;
  366.  
  367.   points += Player.cash/500;
  368.  
  369.   for (i=0;i<MAXITEMS;i++) 
  370.     if (Player.possessions[i] != NULL)
  371.       points += Player.possessions[i]->level*(Player.possessions[i]->known+1);
  372.  
  373.   for (i=0;i<MAXPACK;i++) 
  374.     if (Player.pack[i] != NULL)
  375.       points += Player.pack[i]->level*(Player.pack[i]->known+1);
  376.  
  377.   for (i=0;i<NUMRANKS;i++) {
  378.     if (Player.rank[i] == 5) points += 500;
  379.     else points += 20*Player.rank[i];
  380.   }
  381.   
  382.   if (Player.hp < 1)
  383.     points = (points / 2);
  384.   
  385.   else if (Player.rank[ADEPT])
  386.     points *= 10;
  387.   
  388.   return(points);
  389. }
  390.  
  391.  
  392. /* returns the 24 hour clock hour */
  393. int hour()
  394. {
  395.   return(((Time+720) / 60) % 24);
  396. }
  397.  
  398. /* returns 0, 10, 20, 30, 40, or 50 */
  399. int showminute()
  400. {
  401.   return(((Time % 60)/10)*10);
  402. }
  403.  
  404. /* returns the 12 hour clock hour */
  405. int showhour()
  406. {
  407.   int showtime;
  408.   if ((hour() == 0) || (hour() == 12)) showtime = 12;
  409.   else showtime = (hour() % 12);
  410.   return(showtime);
  411. }
  412.  
  413. /* nighttime is defined from 9 PM to 6AM */
  414. int nighttime()
  415. {
  416.   return((hour() > 20) || (hour() < 7));
  417. }
  418.  
  419. char *getarticle(str)
  420. char *str;
  421. {
  422.   if ((str[0]=='a') || (str[0]=='A') ||
  423.       (str[0]=='e') || (str[0]=='E') ||
  424.       (str[0]=='i') || (str[0]=='I') ||
  425.       (str[0]=='o') || (str[0]=='O') ||
  426.       (str[0]=='u') || (str[0]=='U') ||
  427.       (((str[0]=='h') || (str[0]=='H')) && 
  428.        ((str[1]=='i') || (str[1]=='e'))))
  429.     return("an ");
  430.   else return("a ");
  431. }
  432.  
  433. int day()
  434. {
  435.   return ((Date % 30) + 1);
  436. }
  437.  
  438. char *ordinal(number)
  439. int number;
  440. {
  441.   if ((number == 11) || (number == 12) || (number == 13)) return("th");
  442.   else  switch(number % 10) {
  443.     case 1:return("st");break;
  444.     case 2:return("nd");break;
  445.     case 3:return("rd");break;
  446.     default: return("th");break;
  447.   }
  448. }
  449.        
  450. char *month()
  451. {
  452.   switch((Date % 360) / 30) {
  453.     case 0: return("Freeze"); break;
  454.     case 1: return("Ice"); break;
  455.     case 2: return("Mud"); break;
  456.     case 3: return("Storm"); break;
  457.     case 4: return("Breeze"); break;
  458.     case 5: return("Light"); break;
  459.     case 6: return("Flame"); break;
  460.     case 7: return("Broil"); break;
  461.     case 8: return("Cool"); break;
  462.     case 9: return("Haunt"); break;
  463.     case 10: return("Chill"); break;
  464.     case 11: return("Dark"); break;
  465.     case 12: return("Twixt"); break;
  466.   }
  467. }
  468.  
  469.  
  470. /* finds floor space on level with buildaux not equal to baux, 
  471. sets x,y there. There must *be* floor space somewhere on level.... */
  472.  
  473. void findspace(x,y,baux)
  474. int *x,*y;
  475. {
  476.   int i,j,k,l,done=FALSE;
  477.   i = k = random_range(WIDTH);
  478.   j = l = random_range(LENGTH);
  479.   do {
  480.     i++;
  481.     if (i >= WIDTH) {
  482.       i = 0;
  483.       j++;
  484.       if (j > LENGTH)
  485.     j = 0;
  486.       done = ((i == k) && (j == l));
  487.     }
  488.     done = done || 
  489.       ((Level->site[i][j].locchar == FLOOR) &&
  490.        (Level->site[i][j].creature == NULL) &&
  491.        (Level->site[i][j].buildaux != baux));
  492.   } while (! done);
  493.   *x = i;
  494.   *y = j;
  495. }
  496.  
  497. /* is prefix a prefix of s? */
  498. int strprefix(prefix,s)
  499. char *prefix,*s;
  500. {
  501.   int i=0,matched=TRUE;
  502.   if (strlen(prefix) > strlen(s)) return(FALSE);
  503.   else {
  504.     while (matched && (i<strlen(prefix))) {
  505.       matched = (prefix[i] == s[i]);
  506.       i++;
  507.     }
  508.     return(matched);
  509.   }
  510. }
  511.  
  512. int confirmation()
  513. {
  514.   switch(random_range(4)) {
  515.   case 0:  mprint("Are you sure? [yn] "); break;
  516.   case 1:  mprint("Certain about that? [yn] "); break;
  517.   case 2:  mprint("Do you really mean it? [yn] "); break;
  518.   case 3:  mprint("Confirm that, would you? [yn] "); break;
  519.   }
  520.   return(ynq()=='y');
  521. }
  522.  
  523.  
  524. /* is character c a member of string s */
  525. int strmem(c,s)
  526. char c;
  527. char *s;
  528. {
  529.   int i,found=FALSE;
  530.   for(i=0;((i<strlen(s)) && (! found));i++)
  531.     found = (s[i] == c);
  532.   return(found);
  533. }
  534.  
  535.  
  536. /* returns true if its ok to get rid of a level */
  537. int ok_to_free(level)
  538. plv level;
  539. {
  540.   if (level == NULL) return(FALSE);
  541.   else return((level->environment != E_CITY) &&
  542.           (level->environment != E_VILLAGE) &&
  543.           (level->environment != Current_Dungeon));
  544. }
  545.  
  546.  
  547. void calc_weight()
  548. {
  549.   int i,weight=0;
  550.  
  551.   for(i=1;i<MAXITEMS;i++) 
  552.     if (Player.possessions[i] != NULL)
  553.       weight += Player.possessions[i]->weight *
  554.     Player.possessions[i]->number;
  555.  
  556.   if ((Player.possessions[O_WEAPON_HAND] != NULL) &&
  557.       (Player.possessions[O_READY_HAND] == Player.possessions[O_WEAPON_HAND]))
  558.     weight -= Player.possessions[O_READY_HAND]->weight *
  559.       Player.possessions[O_READY_HAND]->number;
  560.       
  561.   for(i=1;i<MAXPACK;i++) 
  562.     if (Player.pack[i] != NULL)
  563.       weight += Player.pack[i]->weight *
  564.     Player.pack[i]->number;
  565.  
  566.   Player.itemweight = weight;
  567.  
  568.   dataprint();
  569. }
  570.       
  571. /* alloc just enough string space for str, strcpy, and return pointer */
  572. char *salloc(str)
  573. char *str;
  574. {
  575.   char *s=calloc((unsigned)(strlen(str)+1),sizeof(char));
  576.   strcpy(s,str);
  577.   return(s);
  578. }
  579.